/**
 * @class   wosh::building::Room
 * @brief   BuildingObject representing a generic (real) room of an house.
 *          
 *          wosh::building::Room is usually a child of wosh::building::Floor
 *
 *
 ****************************************************************************
 * @version 0.8.399 $Id: Room.h 2863 2010-08-07 04:28:58Z alex $
 * @author  Alessandro Polo
 ****************************************************************************/
/* Copyright (c) 2007-2010, WOSH - Wide Open Smart Home 
 * by Alessandro Polo - OpenSmartHome.com
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the OpenSmartHome.com WOSH nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY Alessandro Polo ''AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL Alessandro Polo BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ****************************************************************************/

#ifndef __WOSH_Building_Room_H__
 #define __WOSH_Building_Room_H__

 #include <framework/building/BuildingObject.h>


namespace wosh {
 namespace building {

 #define _Room_VERSION					0.903

 #define _Room_KEY_AccessTo				"AccessTo"

 #define _Room_KEY_PresenceState		"PresenceState"
 #define _Room_KEY_PresenceStateTs		"PresenceStateTs"

 #define _Room_KEY_LightState			"LightState"
 #define _Room_KEY_LightStateTs			"LightStateTs"		///< An explanation


 #define _Room_KEY_NoiseState			"NoiseState"		///< field: NoiseState 
 #define _Room_KEY_NoiseStateTs			"NoiseStateTs"		///< field: timestamp of NoiseState

 #define _Room_METHOD_lights_on			"lights_on"			///< method: turn lights on
 #define _Room_METHOD_lights_off		"lights_off"		///< method: turn lights off
 #define _Room_METHOD_lights_fade		"lights_fade"		///< method: fade lights <ARG>

 #define _Room_EVENT_PresenceChanged	"PresenceChanged"
 #define _Room_EVENT_LightChanged		"LightChanged"
 #define _Room_EVENT_NoiseChanged		"NoiseChanged"


class Room : public BuildingObject
 {
	WOSH_BUILDINGOBJECT(wosh::building::Room)

	public:
		/**
		 * @brief Presence status of the room (people detected/empty)
		 * @note  timestamp of the information is stored
		 *        in Properties as key _Room_KEY_PresenceStateTs
		 */
		enum PRESENCE_STATE {
			PRESENCE_UNKNOWN	= 0x00,	///< state is unknown
			PRESENCE_EMPTY		= 0x01,	///< room is empty
			PRESENCE_DETECTED	= 0x02	///< there are users within the room
		};
		/**
		 * @brief Light status of the room (dark, light)
		 * @note  timestamp of the information is stored
		 *        in Properties as key _Room_KEY_LightStateTs
		 */
		enum LIGHT_STATE {
			LIGHT_UNKNOWN	= 0x00,	///< state is unknown
			LIGHT_DARK		= 0x01,	///< room is dark
			LIGHT_BRIGHT	= 0x02,	///< room is bright
			LIGHT_NATURAL	= 0x03	///< same as outside (natural light)
		};
		/**
		 * @brief noise states
		 * @note  timestamp of the information is stored
		 *        in Properties as key _Room_KEY_NoiseStateTs
		 */
		enum NOISE_STATE {
			NOISE_UNKNOWN	= 0x00,	///< state is unknown
			NOISE_SILENT	= 0x01,	///< no noise
			NOISE_DETECTED	= 0x02	///< noisy
		};

	public:
		/**
		 * @brief  Default constructor, setup type/interface, register
		 *         custom Methods and Properties.
		 */
		Room();
		/**
		 * @brief  Copy constructor.
		 * @param m [in] the source object to be copied
		 */
		Room( const Room& m ) : BuildingObject(m) { }
		/**
		 * @brief  Empty destructor.
		 */
		virtual ~Room() { }


	public:
		virtual void busMessageChild( const Message& message );

//@}
/** @name Room Interface - 
 * @{
 ******************************************************************************/
	public:
		/**
		 * @brief   Turn lights on. Provided for testing.
		 * @see     mmDoLightsTurnOn()
		 * @return WRET_OK
		 */
		virtual WRESULT lightsTurnOn()					{ return mmDoLightsTurnOn(NULL); }
		/**
		 * @brief   Turn lights off. Provided for testing.
		 * @see     mmDoLightsTurnOff()
		 * @return WRET_OK
		 */
		virtual WRESULT lightsTurnOff()					{ return mmDoLightsTurnOff(NULL); }

	public:
		/**
		 * @brief   Get last known presence state
		 * @return current presence state (enum)
		 */
		Room::PRESENCE_STATE getPresenceState() const	{ return this->statePresence; }
		/**
		 * @brief   Get state as a literal string
		 */
		inline const char* getPresenceStateAsString() const	{ return getPresenceStateAsString(this->statePresence); }
		/**
		 * @brief   Get presence state as a literal string
		 * @param [in] state the state to be translated
		 * @return string representing the state {'EMPTY', 'DETECTED', 'UNKNOWN'}
		 */
		static const char* getPresenceStateAsString( Room::PRESENCE_STATE state );
		/**
		 * @brief   Get presence state from a literal string
		 * @param [in] stateAsString the state represented as string
		 * @return state mapped to input (PRESENCE_UNKNOWN by default)
		 */
		Room::PRESENCE_STATE getPresenceStateFromString( const char* stateAsString );
		/**
		 * @brief   Get last known light state
		 * @return current light state (enum)
		 */
		Room::LIGHT_STATE getLightState() const				{ return this->stateLight; }
		/**
		 * @brief   Get state as a literal string
		 */
		inline const char* getLightStateAsString() const	{ return getLightStateAsString(this->stateLight); }
		/**
		 * @brief   Get light state as a literal string
		 * @param [in] state the state to be translated
		 * @return string representing the state {'DARK', 'BRIGHT', 'NATURAL', 'UNKNOWN'}
		 */
		static const char* getLightStateAsString( Room::LIGHT_STATE state );
		/**
		 * @brief   Get light state from a literal string
		 * @param [in] stateAsString the state represented as string
		 * @return state mapped to input (LIGHT_UNKNOWN by default)
		 */
		Room::LIGHT_STATE getLightStateFromString( const char* stateAsString );
		/**
		 * @brief   Get last known noise state
		 * @return current noise state (enum)
		 */
		Room::NOISE_STATE getNoiseState() const				{ return this->stateNoise; }
		/**
		 * @brief   Get state as a literal string
		 */
		inline const char* getNoiseStateAsString() const	{ return getNoiseStateAsString(this->stateNoise); }
		/**
		 * @brief   Get noise state as a literal string
		 * @param [in] state the state to be translated
		 * @return string representing the state {'SILENT', 'DETECTED', 'UNKNOWN'}
		 */
		static const char* getNoiseStateAsString( Room::NOISE_STATE state );
		/**
		 * @brief   Get noise state from a literal string
		 * @param [in] stateAsString the state represented as string
		 * @return state mapped to input (NOISE_UNKNOWN by default)
		 */
		Room::NOISE_STATE getNoiseStateFromString( const char* stateAsString );

//@}
/** @name Serialization interface
 * @{
 ******************************************************************************/
	public:
		virtual bool updateHash( DataHashContext* hash_context ) const;
//@}
/** @name Internal methods
 * @{
 ******************************************************************************/
	protected:
		/**
		 * @brief   Register Methods and Properties. Called from Constructor (only).
		 */
		virtual void init();

		/**
		 * @brief   Set the new presence state, update Properties (value and its timestamp).
		 *          Eventually raises _Room_EVENT_PresenceChanged event.
		 * @param [in] state the new presence state
		 * @param [in] raise_event flag which force the raising of Message event (wosh::Fact).
		 *          wosh::BuidlingObject::raiseAlwaysEvents flag will override this parameter.
		 */
		void setPresenceState( Room::PRESENCE_STATE state, bool raise_event = true, const SecurityToken* source_token = NULL );
		/**
		 * @brief   Set the new light state, update Properties (value and its timestamp).
		 *          Eventually raises _Room_EVENT_LightChanged event.
		 * @param [in] state the new light state
		 * @param [in] raise_event flag which force the raising of Message event (wosh::Fact).
		 *          wosh::BuidlingObject::raiseAlwaysEvents flag will override this parameter.
		 */
		void setLightState( Room::LIGHT_STATE state, bool raise_event = true, const SecurityToken* source_token = NULL );
		/**
		 * @brief   Set the new noise state, update Properties (value and its timestamp).
		 *          Eventually raises _Room_EVENT_NoiseChanged event.
		 * @param [in] state the new noise state
		 * @param [in] raise_event flag which force the raising of Message event (wosh::Fact).
		 *          wosh::BuidlingObject::raiseAlwaysEvents flag will override this parameter.
		 */
		void setNoiseState( Room::NOISE_STATE state, bool raise_event = true, const SecurityToken* source_token = NULL );

//@}
	private:
		/**
		 * @brief   Turn the light on. Mapped to _Room_METHOD_lights_on
		 *          Sending command _Appliance_METHOD_on to all children of _Appliance_TYPE type.
		 * @param [in] security Security Token associated with request.
		 *          Since the method generates a Message and it is raised by an user/object
		 *          it should (for security reason) forward the ownership of the request.
		 * @return WRET_OK
		 * @note    defined as MethodWRESULTwSecurityToken 
		 */
		WRESULT mmDoLightsTurnOn( const SecurityToken* security );
		/**
		 * @brief   Turn the light off. Mapped to _Room_METHOD_lights_off
		 *          Sending command _Appliance_METHOD_off to all children of _Appliance_TYPE type.
		 * @param [in] security Security Token associated with request.
		 *          Since the method generates a Message and it is raised by an user/object
		 *          it should (for security reason) forward the ownership of the request.
		 * @return WRET_OK
		 * @note    defined as MethodWRESULTwSecurityToken 
		 */
		WRESULT mmDoLightsTurnOff( const SecurityToken* security );

	protected:
		Room::PRESENCE_STATE statePresence;	///< current presence state, shadow Property is _Room_KEY_PresenceState
		Room::LIGHT_STATE stateLight;		///< current light state, shadow Property is _Room_KEY_LightState
		Room::NOISE_STATE stateNoise;		///< current noise state, shadow Property is _Room_KEY_NoiseState

}; // class def



/**
 * @class   wosh::building::Room_PresenceChanged
 * @brief   Raised when door state is changed (such as open to closed).
 *
 * Internally, data is stored as wosh::List. Supports also wosh::Variant type.
 *
 * Fields are:
 *  - \c door_state [Variant::INTEGER] (always present, first item of the list)
 *  - \c previous_presence_state (optional, second item of the list)
 *
 * Some getters are provided for convenience:
 * \code

 * \endcode
 *
 * @see     wosh::Fact
 * @see     wosh::building:Room
 ****************************************************************************
 * @version 0.8.399 $Id: Room.h 2863 2010-08-07 04:28:58Z alex $
 * @author  Alessandro Polo
 ****************************************************************************/
class Room_PresenceChanged : public wosh::Fact
 {
	WOSH_SERIALIZABLE(wosh::building::Room_PresenceChanged)

	public:
		/**
		 * @brief  Empty constructor.
		 */
		Room_PresenceChanged()
			: wosh::Fact(_Room_EVENT_PresenceChanged) { }
		/**
		 * @brief  Constructor with initializers.
		 * @param current_presence_state [in] current presence state of the room
		 */
		Room_PresenceChanged( Room::PRESENCE_STATE current_presence_state );
		/**
		 * @brief  Constructor with initializers.
		 * @param current_presence_state [in] current presence state of the room
		 * @param previous_presence_state [in] previous presence state of the room
		 */
		Room_PresenceChanged( Room::PRESENCE_STATE current_presence_state, Room::PRESENCE_STATE previous_presence_state );
		/**
		 * @brief  Copy constructor.
		 * @param m [in] the source object to be copied
		 */
		Room_PresenceChanged( const Room_PresenceChanged& m )
			: wosh::Fact(m) { }
		/**
		 * @brief  Empty destructor.
		 */
		virtual ~Room_PresenceChanged() { }

	public:
		/**
		 * @brief   Get presence state (opened, closed, unknown)
		 * @return  current presence state (enum)
		 */
		Room::PRESENCE_STATE getPresenceState() const;

		/**
		 * @brief   Get previous presence state (opened, closed, unknown)
		 * @return  previous presence state (enum)
		 */
		Room::PRESENCE_STATE getPreviousPresenceState() const;


}; // class def




/**
 * @class   wosh::building::Room_LightChanged
 * @brief   Raised when door state is changed (such as open to closed).
 *
 * Internally, data is stored as wosh::List. Supports also wosh::Variant type.
 *
 * Fields are:
 *  - \c door_state [Variant::INTEGER] (always present, first item of the list)
 *  - \c previous_door_state (optional, second item of the list)
 *
 * Some getters are provided for convenience:
 * \code

 * \endcode
 *
 * @see     wosh::Fact
 * @see     wosh::building:Room
 ****************************************************************************
 * @version 0.8.399 $Id: Room.h 2863 2010-08-07 04:28:58Z alex $
 * @author  Alessandro Polo
 ****************************************************************************/
class Room_LightChanged : public wosh::Fact
 {
	WOSH_SERIALIZABLE(wosh::building::Room_LightChanged)

	public:
		/**
		 * @brief  Empty constructor.
		 */
		Room_LightChanged()
			: wosh::Fact(_Room_EVENT_LightChanged) { }
		/**
		 * @brief  Constructor with initializers.
		 * @param current_door_state [in] current light-state of the door
		 */
		Room_LightChanged( Room::LIGHT_STATE current_door_state );
		/**
		 * @brief  Constructor with initializers.
		 * @param current_door_state [in] current light-state of the room
		 * @param previous_door_state [in] previous light-state of the room
		 */
		Room_LightChanged( Room::LIGHT_STATE current_door_state, Room::LIGHT_STATE previous_door_state );
		/**
		 * @brief  Copy constructor.
		 * @param m [in] the source object to be copied
		 */
		Room_LightChanged( const Room_LightChanged& m )
			: wosh::Fact(m) { }
		/**
		 * @brief  Empty destructor.
		 */
		virtual ~Room_LightChanged() { }

	public:
		/**
		 * @brief   Get room light-state (opened, closed, unknown)
		 * @return  current room light-state (enum)
		 */
		Room::LIGHT_STATE getLightState() const;

		/**
		 * @brief   Get previous room light-state (opened, closed, unknown)
		 * @return  previous room light-state (enum)
		 */
		Room::LIGHT_STATE getPreviousLightState() const;


}; // class def




/**
 * @class   wosh::building::Room_NoiseChanged
 * @brief   Raised when door state is changed (such as open to closed).
 *
 * Internally, data is stored as wosh::List. Supports also wosh::Variant type.
 *
 * Fields are:
 *  - \c door_state [Variant::INTEGER] (always present, first item of the list)
 *  - \c previous_door_state (optional, second item of the list)
 *
 * Some getters are provided for convenience:
 * \code

 * \endcode
 *
 * @see     wosh::Fact
 * @see     wosh::building:Room
 ****************************************************************************
 * @version 0.8.399 $Id: Room.h 2863 2010-08-07 04:28:58Z alex $
 * @author  Alessandro Polo
 ****************************************************************************/
class Room_NoiseChanged : public wosh::Fact
 {
	WOSH_SERIALIZABLE(wosh::building::Room_NoiseChanged)

	public:
		/**
		 * @brief  Empty constructor.
		 */
		Room_NoiseChanged()
			: wosh::Fact(_Room_EVENT_NoiseChanged) { }
		/**
		 * @brief  Constructor with initializers.
		 * @param current_noise_state [in] current noise-state of the room
		 */
		Room_NoiseChanged( Room::NOISE_STATE current_noise_state );
		/**
		 * @brief  Constructor with initializers.
		 * @param current_noise_state [in] current noise-state of the room
		 * @param previous_noise_state [in] previous noise-state of the room
		 */
		Room_NoiseChanged( Room::NOISE_STATE current_noise_state, Room::NOISE_STATE previous_noise_state );
		/**
		 * @brief  Copy constructor.
		 * @param m [in] the source object to be copied
		 */
		Room_NoiseChanged( const Room_NoiseChanged& m )
			: wosh::Fact(m) { }
		/**
		 * @brief  Empty destructor.
		 */
		virtual ~Room_NoiseChanged() { }

	public:
		/**
		 * @brief   Get room noise-state (opened, closed, unknown)
		 * @return  current room noise-state (enum)
		 */
		Room::NOISE_STATE getNoiseState() const;

		/**
		 * @brief   Get previous room noise-state (opened, closed, unknown)
		 * @return  previous room noise-state (enum)
		 */
		Room::NOISE_STATE getPreviousNoiseState() const;


}; // class def




 }; // namespace building
}; // namespace wosh

#endif //__WOSH_Building_Room_H__
